﻿namespace StockSharp.Algo.Indicators.Oscillator
{
	using System.ComponentModel;

	using StockSharp.Algo.Indicators.Misc;

	/// <summary>
	/// Осциллятор ценовых моментов Чанде.
	/// </summary>
	[DisplayName("CMO")]
	[Description("Осциллятор ценовых моментов Чанде.")]
	public class ChandeMomentumOscillator : LengthIndicator<decimal>
	{
		private readonly Sum _cmoUp = new Sum();
		private readonly Sum _cmoDn = new Sum();
		bool _isInitialized;
		decimal _last;

		/// <summary>
		/// Создать <see cref="ChandeMomentumOscillator"/>.
		/// </summary>
		public ChandeMomentumOscillator()
			: base(typeof(decimal))
		{
		}

		/// <summary>
		/// Длина периода.
		/// </summary>
		public override int Length
		{
			get
			{
				return _cmoUp.Length;
			}
			set
			{
				_cmoDn.Length = _cmoUp.Length = value;
				Reset();
			}
		}

		/// <summary>
		/// Сформирован ли индикатор.
		/// </summary>
		public override bool IsFormed { get { return _cmoUp.IsFormed; } }

		/// <summary>
		/// Обработать входное значение.
		/// </summary>
		/// <param name="input">Входное значение.</param>
		/// <returns>Результирующее значение.</returns>
		protected override decimal OnProcess(IIndicatorValue input)
		{
			var newValue = input.GetValue<decimal>();

			if (!_isInitialized)
			{
				_last = newValue;
				_isInitialized = true;
				return this.GetCurrentValue();
			}

			var delta = newValue - _last;

			var upValue = _cmoUp.Process(input.SetValue(delta > 0 ? delta : 0m)).GetValue<decimal>();
			var downValue = _cmoDn.Process(input.SetValue(delta > 0 ? 0m : -delta)).GetValue<decimal>();
		
			_last = newValue;
			var value = (upValue + downValue) == 0 ? 0 : 100m*(upValue - downValue)/(upValue + downValue);
			return IsFormed ? value : this.GetCurrentValue();
		}
	}
}